/*
 * tree_visitors.h
 *
 *  Created on: May 1, 2011
 *      Author: tqlong
 */

#ifndef TREE_VISITORS_H_
#define TREE_VISITORS_H_

/** An rang visitor on KDTree */
template <typename T>
struct RangeVisitor
{
  typedef T                        tree_type;
  typedef typename T::dataset_type dataset_type;
  typedef typename T::vec_type     vec_type;
  typedef typename T::box_type     box_type;
  typedef std::vector<int>         vint_type;
  typedef std::vector<double>       vdouble_type;

  vec_type     m_query;
  double m_r;
  bool m_all;
  bool m_found;
  double m_norm;
  vint_type    m_idx;
  vdouble_type m_dist;

  RangeVisitor(const vec_type& query, double r, bool all, double norm) :
    m_query(query), m_r(r), m_all(all), m_found(false), m_norm(norm)
  {
//    Log::m_log << "norm=" << m_norm << endl;
  }

  bool ok(tree_type* t)
  {
    return t->box().lowerBound(m_query, m_norm) <= m_r;
  }

  void process(tree_type* t, int i)
  {
    double d = (m_norm != std::numeric_limits<double>::infinity()) ?
        arma::norm(m_query - t->get(i), (int)m_norm) : arma::norm(m_query - t->get(i), "inf");
    if (d < m_r) {
      m_idx.push_back(t->rootIdx(i));
      m_dist.push_back(d);
      m_found = true;
    }
  }

  bool isDone()
  {
    return !m_all && m_found;
  }
};

#endif /* TREE_VISITORS_H_ */
